import {
  createMemo,
  mergeProps,
  Show,
  splitProps,
  type ParentComponent,
  type ValidComponent,
} from "solid-js";
import type { ButtonProps } from "./types";
import Spinner from "@lib/Spinner";
import "./index.scss";
import type { JSX } from "solid-js/jsx-runtime";
import { IsNotNullOrUndefined } from "@lib/helper";

const BsButton: ParentComponent<ButtonProps> = (props) => {
  const [local, attributes] = splitProps(
    mergeProps({ variant: "primary", loadingDelay: 500 }, props),
    [
      "ref",
      "$ServerOnly",
      "classList",
      "children",
      "variant",
      "size",
      "outline",
      "disabled",
      "loading",
      "spinnerProps",
      "loadingDelay",
      "icon",
      "active",
    ]
  );

  const classList = createMemo(() => {
    return {
      ["btn"]: true,
      [`btn${local.outline ? "-outline" : ""}-${local.variant}`]:
        local.variant !== undefined,
      [`btn-${local.size}`]: local.size !== undefined,
      active: local.active,
      ...local.classList,
    };
  });

  const spinnerAttributes = mergeProps(
    {
      // classList: { "me-1": local.children !== undefined },
      sm: true,
    },
    local.spinnerProps
  );

  const spinnerClassList = createMemo(() => {
    return {
      ...spinnerAttributes?.classList,
      ["btn-loading"]: true,
      ["show"]: local.loading,
    };
  });

  const spinnerStyle = createMemo(() => {
    if (local.size !== undefined) {
      const style = local.spinnerProps?.style || {};

      style["width"] = "var(--bs-btn-font-size)";
      style["height"] = "var(--bs-btn-font-size)";

      return style;
    }

    return local.spinnerProps?.style;
  });

  const iconStyle = createMemo(() => {
    const style: JSX.CSSProperties = {};

    style["width"] = "var(--bs-btn-font-size)";
    style["height"] = "var(--bs-btn-font-size)";

    return style;
  });

  const iconClassList = createMemo(() => {
    return {
      "me-1": local.children !== undefined,
    };
  });

  const icon = createMemo(() => {
    if (!local.icon) {
      return undefined;
    }

    if (typeof local.icon == "function") {
      return local.icon;
    }

    return () => local.icon as ValidComponent;
  });

  return (
    <button
      type="button"
      ref={local.ref}
      {...attributes}
      classList={classList()}
      disabled={local.disabled || local.loading}
    >
      <span
        class="fade show"
        classList={iconClassList()}
        style={{
          display:
            IsNotNullOrUndefined(local.icon) || local.loading
              ? "inline-block"
              : "none",
        }}
      >
        <Show when={IsNotNullOrUndefined(local.icon) && !local.loading}>
          {local.icon}
        </Show>
        <Spinner
          {...spinnerAttributes}
          classList={spinnerClassList()}
          style={spinnerStyle()}
        ></Spinner>
      </span>

      {local.children}
    </button>
  );
};

export default BsButton;
